/**
 * Percentile module must be in place for this module to work
 * @param chart
 * @constructor
 */
function IntelligentAxis( chart ) {
  this.chart = chart;
  this.percentile = this.chart.getPercentile();
  this.logger = console;
  window.logger = console;
}

IntelligentAxis.prototype.isCompatible = function( series1, series2, overlapPercentage, thresholdPercentage ) {
  var percentile1 = series1.seriesPercentile;
  var percentile2 = series2.seriesPercentile;

  if ( !isValued(percentile1) || !isValued(percentile2 )) {
    logger.info( "One of the series percentile is null ", percentile1, percentile2 );
    return true;
  }

  var maxPercentage = 1 - ( Math.abs ( ( percentile1.max - percentile2.max ) / Math.max( percentile1.max, percentile2.max ) ) );
  var maxPlus = maxPercentage * ( 1 + thresholdPercentage );
  var minPercentage = 1 - ( Math.abs ( ( percentile1.min - percentile2.min ) / Math.max( percentile1.min, percentile2.min ) ) );
  var minPlus = minPercentage * ( 1 + thresholdPercentage );

  logger.info( "Series 1:", series1.name, "Percentile: ",percentile1,
          " Series 2 ", series2.name, "Percentile: ", percentile2,
          "Max Overlap: ", maxPercentage,
          "Max Plus: ", maxPlus,
          "Min Overlap: ", minPercentage,
          "Min Plus: ", minPlus,
          "Target Overlap %: ", overlapPercentage, "Threshold %:", thresholdPercentage  );

  return maxPercentage >= overlapPercentage && minPercentage >= overlapPercentage;
}

IntelligentAxis.prototype.appendSeries = function( axisGrouping, incomingSeries, overlapPercentage, thresholdPercentage ) {
  if ( !isValued( axisGrouping ) ) return ;
  var intelligentAxis = this;
  var found = false;
  axisGrouping.forEach( function ( seriesPerAxis ){
    if ( found ) return;
    seriesPerAxis.forEach( function( series ) {
      if ( !found && intelligentAxis.isCompatible( incomingSeries, series, overlapPercentage, thresholdPercentage  ) ) {
        seriesPerAxis.push( incomingSeries );
        found = true;
        //found a location
        return;
      }
    });
  });
  //no matches, create new array and add to end
  if ( !found ) axisGrouping.push( [ incomingSeries ] );
}



/**
 * Go through all chart series and see if they need to split
 */
IntelligentAxis.prototype.processSeries = function() {

  var axisType = this.chart.getOptionParameter( KEY_AXIS_TYPE );
  if(axisType !== "intelligent") return;

  var start = Date.now();
  //passing these in so that one calculation uses the same parameters in case they change
  var overlapPercentage = this.chart.getOptionParameter( KEY_AXIS_OVERLAP_PCT );
  var thresholdPercentage = this.chart.getOptionParameter( KEY_AXIS_OVERLAP_THRESHOLD_PCT );

  // var overlapPercentage = 0.9;
  // var thresholdPercentage = 0.05;

  //*****MANUAL MODE***
  //var cooldown = this.chart.getOptionParameter( KEY_AXIS_COOLDOWN );
  //*****MANUAL MODE***

  var cooldown = 0;
  var axisGrouping = [];
  var now = Date.now();
  var intelligentAxis = this;
  this.chart.series.forEach( function( series ) {
    if ( series.options.type != "line" || series.isDerivedSeries() ) {
      return;
    }
    var yDataCopy = series.yData.slice( 0 );
    series.seriesPercentile = intelligentAxis.percentile.calculatePercentile( yDataCopy );
    logger.debug( "Percentile for ", series.name, series.seriesPercentile );
    intelligentAxis.appendSeries( axisGrouping, series, overlapPercentage, thresholdPercentage );
  });
  var axisIndex = 0;
  var moved = false;
  axisGrouping.forEach(function( axisSeries ) {
    var currentAxis = intelligentAxis.chart.yAxis.length >= axisIndex + 1 ? axisIndex : null;

    axisSeries.forEach(function( incomingSeries ) {
      var seriesPercentile = incomingSeries.seriesPercentile;
      //dont know why this is missing when collapsing last series
      if ( !isDefined( seriesPercentile ) ) {
        seriesPercentile = {};
      }
      var lastMove = seriesPercentile.lastMove;
      if ( !isDefined(lastMove )) lastMove = null;
      var allowMove = ( lastMove == null || now - lastMove > cooldown * 1000  );
      if ( !allowMove ) console.log( "Not allowing series to move, last move was ", (now - lastMove ), "ms, cooldown: ", cooldown * 1000, "ms" );

      if ( incomingSeries.getYAxisIndex() != axisIndex && allowMove ) {
        console.log( "Moving Series ", incomingSeries.name, " to yaxis at index ", axisIndex, " series percentile: ", seriesPercentile );
        if ( currentAxis == null ) {
          currentAxis =  assignYAxis( "axis-"+(axisIndex+1).toString(), { left: ( axisIndex + 1 ) % 2 == 1 });
          console.log ( "Creating Axis ", axisIndex );
        }
        incomingSeries.update( { yAxis: axisIndex }, false);

        if ( incomingSeries.linkedSeries && incomingSeries.linkedSeries.length > 0 ) {
          incomingSeries.linkedSeries.forEach( function( linked ) {
            linked.update( { yAxis: axisIndex }, false);
          });
        }

        moved = true;
      }
    });
    axisIndex++;
  });
  if ( moved )  {
    this.chart.redraw();
  }
  logger.info( "Intelligent YAxis Processing Elapsed: ", ( Date.now() - start ), "ms" );
}